﻿/*
 * Created by SharpDevelop.
 * User: Corrado Mio
 * Date: 01/06/2012
 * Time: 06:51
 * 
 * Classe factory per gli oggetti Timer.
 * Aggiunge le seguenti funzionalita':
 * 
 * - aggiunge il supporto agli oggetti Runnable
 * - permette di chiamare metodi del tipo Action
 * - si assicura di intercettare le eccezioni
 * 
 * Si tenga presente che il timer, alla scadenza, manda in esecuzione
 * la callback un un Thread del ThreadPool.
 * 
 * Questo implica che:
 * 
 * - se i thread non terminano, si arriva all'OoutOfMemory
 * - se le eccezioni non vengono intercettate, viene terminata l'applicazione
 * 
 */
using System;
using System.Reflection;
using System.Threading;

using log4net;

namespace CSharpExt.Threading
{
    /// <summary>
    /// La classe mette a disposizione una serie di metodi statici per la creazione di
    /// oggetti di tipo Timer ed aggiunge le seguenti funzionalita':
    /// 
    /// - permette di chiamare metodi del tipo Action
    /// - aggiunge il supporto a Runnable
    /// - si assicura di intercettare tutte le eccezioni e farne il log
    /// 
    /// </summary>
    public static class Timers
    {
        #region Factory Methods
        
        // -- Action()
        
        public static Timer Create(Action callback, int dueTime, int period)
        {
            return new Timer(
                (arg) => 
                {  
                    try 
                    {
                        callback();
                    }
                    catch (Exception e)
                    {
                        LogManager.GetLogger("Timer").Error(e, e);
                    }
                }, 
                null, 
                dueTime, 
                period);
        }
        
        
        // -- Action(Object)
        
        public static Timer Create(Action<Object> callbackArg, Object state, int dueTime, int period)
        {
            return new Timer(
                (arg) => 
                {  
                    try 
                    {
                        callbackArg(arg);
                    }
                    catch (Exception e)
                    {
                        LogManager.GetLogger("Timer").Error(e, e);
                    }
                }, 
                state, 
                dueTime, 
                period);
        }

        
        // -- Runnable
        
        public static Timer Create(Runnable runnable, int dueTime, int period)
        {
            return Create(callRunnable, runnable, dueTime, period);
        }
        
        private static void callRunnable(Object arg)
        {
            ((Runnable)arg).Run();
        }
        
        #endregion
    }
}
